/**
 * @Copyright:Copyright (c) 1992 - 2016
 * @Company: TengTong
 */

package com.tengtong.duang.commons.base.impl;

import java.util.Objects;
import java.util.Optional;
import java.util.function.Supplier;

import com.tengtong.duang.commons.base.Result;

/**
 * Result<T> 接口的简单实现
 * 
 * @author Jai
 *
 */
public class SimpleResult<T> implements Result<T> {

	private boolean success;
	
	private T data;
	
	private Throwable exception;
	
	/**
	 * 定义一个空的结果
	 */
	public SimpleResult(){
		this.success = true;
	}
	
	/**
	 * @param b
	 * @param object
	 */
	public SimpleResult(boolean success, T data) {
		this.success = success;
		this.data = data;
		this.exception = null;
	}

	/**
	 * 封装一个可以为 null 的值成为一个结果。（注意，此时 success = true）
	 * 
	 * @param apply
	 * @return
	 */
	public static <U> Result<U> ofNullable(U apply) {
		return new SimpleResult<>(true, apply);
	}

	/**
	 * 封装一个不能为  null 的值成为一个结果。（注意，此时 success = true）
	 * 
	 * @param apply
	 * @return
	 */
	public static <U> Result<U> of(U apply) {
		Objects.requireNonNull(apply);
		return new SimpleResult<>(true, apply);
	}	
	
	/**
	 * 封装一个不能为  null 的值成为一个结果。（注意，此时 success = false）
	 * 
	 * @param apply
	 * @return
	 */
	public static <U> Result<U> ofNoSuccess(U apply) {
		Objects.requireNonNull(apply);
		return new SimpleResult<>(false, apply);
	}	
	
	/**
	 * 将一个 Optional 转换一个 Result
	 * 
	 * @param o
	 * @return
	 */
	public static <U> Result<U> ofOptional(Optional<U> o){
		return ofNullable(o.get());
	}
	
    /**
     * 如果 resolver 是一个 null 值，则返回 empty()，否则返回其数据的包含类
     * 
     * 可以用来 null 的检测
     * 
     * @param resolver
     * @return
     */
    public static <U> Result<U> resolve(Supplier<U> resolver) {
        try {
            U result = resolver.get();
            return ofNullable(result);
        }
        catch (NullPointerException e) {
            return Result.empty();
        }
    }
	
	/* (non-Javadoc)
	 * @see com.tengtong.duang.commons.base.Result#isSuccess()
	 */
	@Override
	public boolean isSuccess() {
		return success;
	}

	/* (non-Javadoc)
	 * @see com.tengtong.duang.commons.base.Result#getValue()
	 */
	@Override
	public T getValue() {
		return data;
	}

	/* (non-Javadoc)
	 * @see com.tengtong.duang.commons.base.Result#getException()
	 */
	@Override
	public Throwable getException() {
		return exception;
	}

	/**
	 * 设置 success 值
	 * @param b
	 * @return
	 */
	public SimpleResult<T> success(boolean b){
		this.success = b;
		return this;
	}
	
	/**
	 * 设置 data
	 * @param d
	 * @return
	 */
	public SimpleResult<T> data(T d){
		this.data = d;
		return this;
	}
	
	/**
	 * 设置 exception
	 * @param t
	 * @return
	 */
	public SimpleResult<T> exception(Throwable t){
		this.exception = t;
		return this;
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		StringBuilder builder = new StringBuilder();
		builder.append("SimpleResult [success=");
		builder.append(success);
		builder.append(", data=");
		builder.append(data);
		builder.append(", exception=");
		builder.append(exception);
		builder.append("]");
		return builder.toString();
	}
	
}
